package com.ruoyi.mongo.service;

import com.mongodb.client.MongoCollection;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.ruoyi.common.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class MongoCommonService {

    @Autowired
    private MongoTemplate mongoTemplate;

    public <T> List<?> getList(T entity, String collectionName) {
        Query query = new Query();
        return getList(entity,query,collectionName);
    }

    public <T> Long getCount(T entity,Query query, String collectionName) {
        return mongoTemplate.count(query,entity.getClass(),collectionName);
    }

    public <T>  AggregationResults<?> getAggregationResults(T entity, Aggregation aggregation, String collectionName) {
        return mongoTemplate.aggregate(aggregation, collectionName, entity.getClass());
    }

    public <T> List<?> getList(T entity,Query query, String collectionName) {
        MongoCollection<Document> collection = mongoTemplate.getCollection(collectionName);
        long countDocuments = collection.countDocuments();
        if (countDocuments == 0) {
            log.info("集合:{}为空", collectionName);
            return null;
        }
        List<?> list = mongoTemplate.find(query, entity.getClass(), collectionName);
        log.info("集合:{}-条件:{}-条数为:{}", collectionName, query.getQueryObject().toJson(), list.size());
        return list;
    }

    public <T> Object getOne(T entity, Query query, String collectionName) {
        return mongoTemplate.findOne(query, entity.getClass(), collectionName);
    }

    /**
     * 插入重复数据时：insert报DuplicateKeyException提示主键重复；save对已存在的数据进行更新。
     * 批处理操作时：insert可以一次性插入整个数据，效率较高；save需遍历整个数据，一次插入或更新，效率较低。
     * */
    public <T> T saveOne(T entity) {
        return mongoTemplate.save(entity);
    }

    public <T> void insertOne(T entity) {
        mongoTemplate.insert(entity);
    }

    public <T> T insertOne(T entity, String collectionName) {
        return mongoTemplate.insert(entity, collectionName);
    }

    public <T> T insertOneAndReturn(T entity, String collectionName) {
        //        log.info("集合:{}插入后的实体:{}",collectionName,inserted);
        return mongoTemplate.insert(entity, collectionName);
    }

    public <T> void insertList(List<T> list) {
        list.forEach(this::insertOne);
        log.info("插入的集合数量{}",list.size());
    }

    public <T> void deleteOne(T entity, String collectionName, Query query) {
        DeleteResult removed = mongoTemplate.remove(query, collectionName);
        log.info("集合:{}中移除的数据:{}",collectionName,removed);
    }

    public void deleteOne(String collectionName, Query query) {
        DeleteResult removed = mongoTemplate.remove(query, collectionName);
        log.info("集合:{}中移除的数据:{}",collectionName,removed);
    }

    public <T> UpdateResult insertOrUpdate(T entity,Query query,Update update, String collectionName) {

        return mongoTemplate.upsert(query,update,entity.getClass(),collectionName);
    }

    public <T> ArrayList<UpdateResult> insertOrUpdate(List<T> list,Query query,Update update, String collectionName) {
        ArrayList<UpdateResult> updateResults = new ArrayList<>();
        log.info("插入或更新的集合:{}", collectionName);
        list.forEach(entity -> {
            UpdateResult updateResult = insertOrUpdate(entity, query, update, collectionName);
            updateResults.add(updateResult);
        });
        return updateResults;
    }

    public <T> void insertList(List<T> list, String collectionName) {
        log.info("数据插入-集合:{},数量:{},时间:{}",collectionName,list.size(), DateUtils.getLocalTime());
        list.forEach(entity -> insertOne(entity,collectionName));
    }

    /**
     * updateFirst更新一个，update更新所有符合条件的
     * */
    public <T> void updateOne(T entity,Update update,Query query, String collection) {
        mongoTemplate.updateFirst(query, update, entity.getClass(),collection);
    }

    public <T> void update(T entity) {
        mongoTemplate.update(entity.getClass());
    }
}
